home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / util / gnu / oleo_src.lha / src / decompile.c < prev    next >
C/C++ Source or Header  |  1992-08-14  |  16KB  |  753 lines

  1. /*    Copyright (C) 1990 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 1, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "funcdef.h"
  20. #include "sysdef.h"
  21.  
  22. #include "global.h"
  23. #include "eval.h"
  24. #include "cell.h"
  25.  
  26. struct pr_node {
  27.     int tightness;
  28.     int len;
  29.     char string[1];
  30. };
  31.  
  32. char *backslash_a_string EXT2(char *, int);
  33.  
  34. static VOIDSTAR save_decomp;
  35. static CELLREF decomp_row;
  36. static CELLREF decomp_col;
  37.  
  38. /* These #defines are so that we don't have to duplicate code below */
  39. #ifdef A0_REFS
  40. #define F0    "@%s()"
  41. #define F1    "@%s(%s)"
  42. #define F2    "@%s(%s,%s)"
  43. #define F3    "@%s(%s,%s,%s)"
  44. #define F4    "@%s(%s,%s,%s,%s)"
  45. #define FN1    "@%s(%s"
  46. #else
  47. #define F0    "%s()"
  48. #define F1    "%s(%s)"
  49. #define F2    "%s(%s,%s)"
  50. #define F3    "%s(%s,%s,%s)"
  51. #define F4    "%s(%s,%s,%s,%s)"
  52. #define FN1    "%s(%s"
  53. #endif
  54.  
  55. /* We decompile things with these wierd node-things.  It's ugly, but it works.
  56.  */
  57. static struct pr_node *
  58. n_alloc FUN3N(int, size, int, tightness, char *, fmt)
  59. {
  60.     struct pr_node *ret;
  61.     va_list args;
  62.  
  63.     ret=ck_malloc(sizeof(struct pr_node)+size+1);
  64.     ret->len=size;
  65.     ret->tightness=tightness;
  66.     var_start(args,fmt);
  67.     vsprintf(ret->string,fmt,args);
  68.     va_end(args);
  69.     return ret;
  70. }
  71.  
  72. #define n_free(x)    free(x)
  73.  
  74. static struct pr_node *
  75. byte_decompile FUN1(unsigned char *, expr)
  76. {
  77.     unsigned char byte;
  78.     double tmp_flt;
  79.     long tmp_lng;
  80.     char *tmp_str;
  81.     struct var *v;
  82.     unsigned long_skp;
  83.     unsigned char save_val;
  84.     unsigned jumpto;
  85.  
  86.     struct pr_node *new = 0;
  87.     int pri;
  88.     int aso;
  89.     char *chr;
  90.  
  91.     static struct pr_node **the_line;
  92.     static int line_alloc;
  93.  
  94.     static struct pr_node **c_node;
  95.     struct function *f;
  96.  
  97.     if(!the_line) {
  98.         the_line=(struct pr_node **)ck_malloc(20*sizeof(struct pr_node *));
  99.         line_alloc=20;
  100.         c_node=the_line;
  101.     }
  102.  
  103. #ifdef TEST
  104.     if(!expr)
  105.         panic("No expression to decompile");
  106. #endif
  107.  next_byte:
  108.      byte= *expr++;
  109.     if(byte<USR1)
  110.          f= &the_funs[byte];
  111.     else if(byte<SKIP) {
  112.         tmp_lng= *expr++;
  113.         f= &usr_funs[byte-USR1][tmp_lng];
  114.     } else
  115.         f= &skip_funs[byte-SKIP];
  116.  
  117.     if(f->fn_argn&X_J)
  118.         jumpto= *expr++;
  119.     else if(f->fn_argn&X_JL) {
  120.         jumpto=expr[0]+((unsigned)(expr[1])<<8);
  121.         expr+=2;
  122.     }
  123. #ifdef TEST
  124.     else
  125.         jumpto=0;
  126. #endif
  127.     switch(GET_COMP(f->fn_comptype)) {
  128.     case C_IF:
  129.         if(expr[jumpto-2]!=SKIP) {
  130.             long_skp=1;
  131.             save_val=expr[jumpto-3];
  132.             expr[jumpto-3]=0;
  133.         } else {
  134.             long_skp=0;
  135.             save_val=expr[jumpto-2];
  136.             expr[jumpto-2]=0;
  137.         }
  138.         c_node[0]=byte_decompile(expr);
  139.         c_node++;
  140.  
  141.         if(long_skp) {
  142.             expr[jumpto-3]=save_val;
  143.             expr+=jumpto;
  144.             jumpto=expr[-2]+((unsigned)(expr[-1])<<8);
  145.         } else {
  146.             expr[jumpto-2]=save_val;
  147.             expr+=jumpto;
  148.             jumpto=expr[-1];
  149.         }
  150.         save_val=expr[jumpto];
  151.         expr[jumpto]=0;
  152.         c_node[0]=byte_decompile(expr);
  153.         c_node-=2;
  154.         expr[jumpto]=save_val;
  155.         expr+=jumpto;
  156.         if(byte==IF || byte==IF_L) {
  157.             if(c_node[0]->tightness<=1)
  158.                 new=n_alloc(8+c_node[0]->len+c_node[1]->len+c_node[2]->len,
  159.                     1,
  160.                     "(%s) ? %s : %s",c_node[0]->string,c_node[1]->string,c_node[2]->string);
  161.             else 
  162.                 new=n_alloc(6+c_node[0]->len+c_node[1]->len+c_node[2]->len,
  163.                     1,
  164.                     "%s ? %s : %s",c_node[0]->string,c_node[1]->string,c_node[2]->string);
  165.         } else
  166.  
  167.             new=n_alloc(6+c_node[0]->len+c_node[1]->len+c_node[2]->len+strlen(f->fn_str),
  168.                 1000,
  169.                 F3,f->fn_str,c_node[0]->string,c_node[1]->string,c_node[2]->string);
  170.         n_free(c_node[0]);
  171.         n_free(c_node[1]);
  172.         n_free(c_node[2]);
  173.         break;
  174.  
  175.     case C_ANDOR:
  176.         save_val=expr[jumpto];
  177.         expr[jumpto]=0;
  178.         c_node[0]=byte_decompile(expr);
  179.         expr[jumpto]=save_val;
  180.         expr+=jumpto;
  181.         c_node++;
  182.         if(ISINFIX(f->fn_comptype)) {
  183.             pri= GET_IN(f->fn_comptype);
  184.             aso= GET_ASO(f->fn_comptype);
  185.             chr= f->fn_str;
  186.             goto do_infix;
  187.         } else
  188.             goto do_fn2;
  189.  
  190.     case C_STR:
  191.         tmp_str=backslash_a_string((char *)expr+jumpto,1);
  192.         new=n_alloc(strlen(tmp_str)+1,
  193.             1000,
  194.             tmp_str);
  195.         break;
  196.  
  197.     case C_CELL:
  198.     {
  199. #ifndef A0_REFS
  200.         int num1,num2;
  201.         char *str;
  202. #endif
  203.         CELLREF row,col;
  204.  
  205.         row=GET_ROW(expr);
  206.         col=GET_COL(expr);
  207.         expr+=EXP_ADD;
  208.  
  209. #ifdef A0_REFS
  210.         new=n_alloc(30,1000,f->fn_str,col_to_str(col),row);
  211. #else
  212.         if(byte&ROWREL) {
  213.             num1=row-decomp_row;
  214.             if(byte&COLREL) {
  215.                 num2=col-decomp_col;
  216.                 if(row==decomp_row && col==decomp_col)
  217.                     str="rc";
  218.                 else if(row==decomp_row) {
  219.                     str="rc[%+d]";
  220.                     num1=num2;
  221.                 } else if(col==decomp_col)
  222.                     str="r[%+d]c";
  223.                 else
  224.                     str=f->fn_str;
  225.             } else if(row==decomp_row) {
  226.                 str="rc%u";
  227.                 num1=num2=col;
  228.             } else {
  229.                 str=f->fn_str;
  230.                 num2=col;
  231.             }
  232.         } else if(byte&COLREL) {
  233.             num1=row;
  234.             num2=col-decomp_col;
  235.             if(col==decomp_col)
  236.                 str="r%uc";
  237.             else
  238.                 str=f->fn_str;
  239.         } else {
  240.             str=f->fn_str;
  241.             num1=row;
  242.             num2=col;
  243.         }
  244.         new=n_alloc(30,1000,str,num1,num2);
  245. #endif
  246.         new->len=strlen(new->string);
  247.     }
  248.         break;
  249.  
  250.     case C_RANGE:
  251.     {
  252. #ifndef A0_REFS
  253.         char tmprbuf[40];
  254.         char tmpcbuf[40];
  255. #endif
  256.         struct rng rng;
  257.  
  258.         GET_RNG(expr,&rng);
  259.         expr+=EXP_ADD_RNG;
  260.  
  261. #ifdef A0_REFS
  262.         new=n_alloc(40,1000,f->fn_str,col_to_str(rng.lc),rng.lr,col_to_str(rng.hc),rng.hr);
  263. #else
  264.         /* Check for special cases */
  265.         if(rng.lr==rng.hr && ((byte&LRREL)?1:0)==((byte&HRREL)?1:0)) {
  266.             if(byte&LRREL) {
  267.                 if(rng.lr==decomp_row) {
  268.                     tmprbuf[0]='r';
  269.                     tmprbuf[1]='\0';
  270.                 } else
  271.                     (void)sprintf(tmprbuf,"r[%+d]",rng.lr-decomp_row);
  272.             } else
  273.                 sprintf(tmprbuf,"r%u",rng.lr);
  274.         } else if((byte&LRREL) && (byte&HRREL)) {
  275.             int r1,r2,rtmp;
  276.  
  277.             r1=rng.lr-decomp_row;
  278.             r2=rng.hr-decomp_row;
  279.             if(r1<r2)
  280.                 rtmp=r1,r1=r2,r2=rtmp;
  281.             (void)sprintf(tmprbuf,"r[%+d:%+d]",r1,r2);
  282.         } else if((byte&LRREL))
  283.             (void)sprintf(tmprbuf,"r[%+d]:%u",rng.lr-decomp_row,rng.hr);
  284.         else if(byte&HRREL)
  285.             (void)sprintf(tmprbuf,"r%u:[%+d]",rng.lr,rng.hr-decomp_row);
  286.         else if(rng.lr<rng.hr)
  287.             (void)sprintf(tmprbuf,"r%u:%u",rng.lr,rng.hr);
  288.         else
  289.             (void)sprintf(tmprbuf,"r%u:%u",rng.hr,rng.lr);
  290.  
  291.         if(rng.lc==rng.hc && ((byte&LCREL)?1:0)==((byte&HCREL)?1:0)) {
  292.             if(byte&LCREL) {
  293.                 if(rng.lc==decomp_col) {
  294.                     tmpcbuf[0]='c';
  295.                     tmpcbuf[1]='\0';
  296.                 } else
  297.                     sprintf(tmpcbuf,"c[%+d]",rng.lc-decomp_col);
  298.             } else
  299.                 sprintf(tmpcbuf,"c%u",rng.lc);
  300.         } else if((byte&LCREL) && (byte&HCREL)) {
  301.             int c1,c2,ctmp;
  302.  
  303.             c1=rng.lc-decomp_col;
  304.             c2=rng.hc-decomp_col;
  305.             if(c1<c2)
  306.                 ctmp=c1,c1=c2,c2=ctmp;
  307.             (void)sprintf(tmpcbuf,"c[%+d:%+d]",c1,c2);
  308.         } else if((byte&LCREL))
  309.             (void)sprintf(tmpcbuf,"c[%+d]:%u",rng.lc-decomp_col,rng.hc);
  310.         else if(byte&HCREL)
  311.             (void)sprintf(tmpcbuf,"c%u:[%+d]",rng.lc,rng.hc-decomp_col);
  312.         else if(rng.lc<rng.hc)
  313.             (void)sprintf(tmpcbuf,"c%u:%u",rng.lc,rng.hc);
  314.         else
  315.             (void)sprintf(tmpcbuf,"c%u:%u",rng.hc,rng.lc);
  316.  
  317.         new=n_alloc(40,1000,"%s%s",tmprbuf,tmpcbuf);
  318. #endif
  319.         new->len=strlen(new->string);
  320.     }
  321.         break;
  322.  
  323.     case C_CONST:
  324.         new=n_alloc(strlen(f->fn_str)+1,1000,f->fn_str);
  325.         break;
  326.  
  327.     case C_FN0:
  328.     case C_FN0X:
  329.     case C_FN0|C_T:
  330.         new=n_alloc(strlen(f->fn_str)+3,
  331.             1000,
  332.             F0,
  333.             f->fn_str);
  334.         break;
  335.  
  336.     case C_FN1:
  337.         --c_node;
  338.         new=n_alloc(c_node[0]->len+strlen(f->fn_str)+3,
  339.             1000,
  340.             F1, f->fn_str, c_node[0]->string);
  341.         n_free(*c_node);
  342.         break;
  343.  
  344.     case C_UNA:
  345.         --c_node;
  346.         if(c_node[0]->tightness<9) {
  347.             new=n_alloc(3+c_node[0]->len,
  348.                 9,
  349.                 "%s(%s)",f->fn_str,c_node[0]->string);
  350.         } else {
  351.             new=n_alloc(1+c_node[0]->len,
  352.                 9,
  353.                 "%s%s",f->fn_str,c_node[0]->string);
  354.         }
  355.         n_free(*c_node);
  356.         break;
  357.  
  358.     case C_INF:
  359.         pri=GET_IN(f->fn_comptype);
  360.         aso=GET_ASO(f->fn_comptype);
  361.         chr=f->fn_str;
  362.  
  363.     do_infix:
  364.         c_node-=2;
  365.         if(c_node[0]->tightness<pri || (c_node[0]->tightness==pri && aso!=1)) {
  366.             if(c_node[1]->tightness<pri || (c_node[1]->tightness==pri && aso!=-1))
  367.                 new=n_alloc(7+c_node[0]->len+c_node[1]->len,
  368.                     pri,
  369.                     "(%s) %s (%s)",c_node[0]->string,chr,c_node[1]->string);
  370.             else
  371.                 new=n_alloc(5+c_node[0]->len+c_node[1]->len,
  372.                     pri,
  373.                     "(%s) %s %s",c_node[0]->string,chr,c_node[1]->string);
  374.         } else if(c_node[1]->tightness<pri || (c_node[1]->tightness==pri && aso!=-1))
  375.             new=n_alloc(5+c_node[0]->len+c_node[1]->len,
  376.                 pri,
  377.                 "%s %s (%s)",c_node[0]->string,chr,c_node[1]->string);
  378.         else
  379.             new=n_alloc(3+c_node[0]->len+c_node[1]->len,
  380.                 pri,
  381.                 "%s %s %s",c_node[0]->string,chr,c_node[1]->string);
  382.         
  383.         n_free(c_node[0]);
  384.         n_free(c_node[1]);
  385.         break;
  386.  
  387.     case C_FN2:
  388.     do_fn2:
  389.         c_node-=2;
  390.         new=n_alloc(c_node[0]->len+c_node[1]->len+strlen(f->fn_str)+5,
  391.             1000,
  392.             F2,f->fn_str,c_node[0]->string,c_node[1]->string);
  393.         n_free(c_node[0]);
  394.         n_free(c_node[1]);
  395.         break;
  396.  
  397.     case C_FN3:
  398.         c_node-=3;
  399.         new=n_alloc(c_node[0]->len+c_node[1]->len+c_node[2]->len+strlen(f->fn_str)+7,
  400.             1000,
  401.             F3,
  402.                 f->fn_str,
  403.                 c_node[0]->string,
  404.                 c_node[1]->string,
  405.                  c_node[2]->string);
  406.         n_free(c_node[0]);
  407.         n_free(c_node[1]);
  408.         n_free(c_node[2]);
  409.         break;
  410.  
  411.     case C_FNN:
  412.         aso= *expr++;
  413.         c_node-=aso;
  414.  
  415.         if(aso==1)
  416.             new=n_alloc(3+c_node[0]->len+strlen(f->fn_str),
  417.                 1000,
  418.                 F1,f->fn_str,c_node[0]->string);
  419.         else {
  420.             new=n_alloc(2+c_node[0]->len+strlen(f->fn_str),
  421.                 1000,
  422.                 FN1,f->fn_str,c_node[0]->string);
  423.             --aso;
  424.             for(pri=1;pri<aso;pri++) {
  425.                 n_free(c_node[0]);
  426.                 c_node[0]=new;
  427.                 new=n_alloc(2+new->len+c_node[pri]->len,
  428.                     1000,
  429.                     "%s, %s",new->string,c_node[pri]->string);
  430.             }
  431.             n_free(c_node[0]);
  432.             c_node[0]=new;
  433.             new=n_alloc(3+new->len+c_node[aso]->len,
  434.                 1000,
  435.                 "%s, %s)",new->string,c_node[aso]->string);
  436.         }
  437.         n_free(c_node[0]);
  438.         break;
  439.  
  440.     case C_FN4:
  441.         c_node-=4;
  442.         new=n_alloc(c_node[0]->len+c_node[1]->len+c_node[2]->len+c_node[3]->len+strlen(f->fn_str)+6,
  443.             1000,
  444.             F4,
  445.                 f->fn_str,
  446.                 c_node[0]->string,
  447.                 c_node[1]->string,
  448.                  c_node[2]->string,
  449.                  c_node[3]->string);
  450.         n_free(c_node[0]);
  451.         n_free(c_node[1]);
  452.         n_free(c_node[2]);
  453.         n_free(c_node[3]);
  454.         break;
  455.  
  456.     case C_ERR:
  457.         tmp_str=(char *)expr+jumpto;
  458.         expr++;
  459.         new=n_alloc(strlen(tmp_str)+1,1000,tmp_str);
  460.         /* bcopy((VOIDSTAR)expr,(VOIDSTAR)&tmp_str,sizeof(char *));
  461.         expr+=sizeof(char *);
  462.         new=n_alloc(strlen(tmp_str)+1,1000,f->fn_str,tmp_str); */
  463.         break;
  464.  
  465.     case C_FLT:
  466.         bcopy((VOIDSTAR)expr,(VOIDSTAR)&tmp_flt,sizeof(double));
  467.         expr+=sizeof(double);
  468.         new=n_alloc(20,1000,f->fn_str,tmp_flt);
  469.         new->len=strlen(new->string);
  470.         break;
  471.  
  472.     case C_INT:
  473.         bcopy((VOIDSTAR)expr,(VOIDSTAR)&tmp_lng,sizeof(long));
  474.         expr+=sizeof(long);
  475.         new=n_alloc(20,1000,f->fn_str,tmp_lng);
  476.         new->len=strlen(new->string);
  477.         break;
  478.  
  479.     case C_VAR:
  480.         bcopy((VOIDSTAR)expr,(VOIDSTAR)&v,sizeof(struct var *));
  481.         expr+=sizeof(struct var *);
  482.         new=n_alloc(strlen(v->var_name)+1,
  483.             1000,
  484.             f->fn_str, v->var_name);
  485.         break;
  486.  
  487.  
  488.     default:
  489.         panic("Bad decompile %d",f->fn_comptype);
  490.     }
  491.     *c_node++=new;
  492.     if(c_node== &the_line[line_alloc]) {
  493.         line_alloc*=2;
  494.  
  495.         the_line=ck_realloc(the_line,line_alloc*sizeof(struct pr_node *));
  496.         c_node= &the_line[line_alloc/2];
  497.     }
  498.  
  499.     if(*expr)
  500.         goto next_byte;
  501.  
  502.     /* if(c_node != &the_line[1]) {
  503.         error_msg("%d values on decompile stack!",c_node - the_line);
  504.         return the_line[0];
  505.     } */
  506.     new= *--c_node;
  507.     /* free(the_line); */
  508.     return new;
  509. }
  510.  
  511. /* Actual entry points to this file */
  512. /* decomp(row, col, cell) returns a string that can be byte_compiled to create
  513.    cell->formula  decomp_free() frees up the allocated string */
  514. char *
  515. decomp FUN3(CELLREF, r, CELLREF, c, CELL *, cell)
  516. {
  517.     struct pr_node *ret;
  518.     char *str;
  519.     extern char *bname[];
  520.     extern char *strdup EXT1(const char *);
  521.     extern char *flt_to_str EXT1(double);
  522.  
  523.     decomp_row=r;
  524.     decomp_col=c;
  525.     if(cell->cell_formula==0) {
  526.         switch(GET_TYP(cell)) {
  527.         case 0:
  528.             str=ck_malloc(1);
  529.             str[0]='\0';
  530.             break;
  531.         case TYP_FLT:
  532.             str=strdup(flt_to_str(cell->cell_flt));
  533.             break;
  534.         case TYP_INT:
  535.             str=ck_malloc(20);
  536.             sprintf(str,"%ld",cell->cell_int);
  537.             break;
  538.         case TYP_STR:
  539.             str=strdup(backslash_a_string(cell->cell_str,1));
  540.             break;
  541.         case TYP_BOL:
  542.             str=strdup(bname[cell->cell_bol]);
  543.             break;
  544.         case TYP_ERR:
  545.             str=strdup(ename[cell->cell_bol]);
  546.             break;
  547. #ifdef TEST
  548.         default:
  549.             str=0;
  550.             panic("Unknown type %d in decomp",GET_TYP(cell));
  551. #endif
  552.         }
  553.         save_decomp=(VOIDSTAR)str;
  554.         return str;
  555.     } else
  556.         ret=byte_decompile(cell->cell_formula);
  557.         save_decomp=(VOIDSTAR)ret;
  558.     return &(ret->string[0]);
  559. }
  560.  
  561. void
  562. decomp_free FUN0()
  563. {
  564. #ifdef TEST
  565.     if(!save_decomp)
  566.         panic("No save decomp");
  567.     n_free(save_decomp);
  568.     save_decomp= (VOIDSTAR)0;
  569. #else
  570.     n_free(save_decomp);
  571. #endif
  572. }
  573.  
  574. /* This takes a string and returns a backslashed form suitable for printing.
  575.    Iff add_quote is true, it'll add "s at the beginning and end.
  576.    Note that this returns a pointer to a static area that is overwritten with
  577.    each call. . .
  578.  */
  579. char *
  580. backslash_a_string FUN2(char *,string, int,add_quote)
  581. {
  582.     char *pf;
  583.     char *pt;
  584.     int ch;
  585.     int size;
  586.     int len;
  587.  
  588.     static char *cbuf;
  589.     static int s_cbuf;
  590.  
  591. #define ALLOC_PT()                \
  592.     len=strlen(pf);                \
  593.     size=pf-string;                \
  594.     if(s_cbuf<3+size+4*len) {        \
  595.         s_cbuf=3+size+4*len;        \
  596.         cbuf= (cbuf) ? ck_realloc(cbuf,s_cbuf) : ck_malloc(s_cbuf); \
  597.     }                    \
  598.     if(size)                \
  599.         bcopy(string,cbuf,size);    \
  600.     pt=cbuf+size;                \
  601.  
  602.  
  603.     pt=0;
  604.     pf=string;
  605.     if(add_quote) {
  606.         ALLOC_PT()
  607.         *pt++='"';
  608.     }
  609.     for(;*pf;pf++) {
  610.         ch= *pf;
  611.         if(ch>=' ' && ch<='~' && ch!='\\' && (ch!='"' || !add_quote)) {
  612.             if(pt)
  613.                 *pt++=ch;
  614.             continue;
  615.         }
  616.  
  617.         if(!pt) {
  618.             ALLOC_PT()
  619.         }
  620.         if(ch=='\\') {
  621.             *pt++='\\';
  622.             *pt++='\\';
  623.         } else if(ch=='"') {
  624.             *pt++='\\';
  625.             *pt++=ch;
  626.         } else {
  627.             *pt++='\\';
  628.             *pt++=((ch>>6)&0x3)+'0';
  629.             *pt++=((ch>>3)&0x7)+'0';
  630.             *pt++=( ch    &0x7)+'0';
  631.         }
  632.     }
  633.     if(add_quote)
  634.         *pt++='"';
  635.     if(pt) {
  636.         *pt++='\0';
  637.         return cbuf;
  638.     }
  639.     return string;
  640. }
  641.  
  642. #ifdef TEST
  643. void
  644. dbg_print_formula FUN1(unsigned char *,expr)
  645. {
  646.     unsigned char byte;
  647.     struct function *f;
  648.     double tmp_flt;
  649.     char *tmp_str;
  650.     long tmp_int;
  651.     struct var *v;
  652.     struct rng rng;
  653.     char *buf;
  654.     unsigned jumpto;
  655.     extern char print_buf[];
  656.     extern char *strcpy();
  657.  
  658.     if(!expr)
  659.         return;
  660.     strcpy(print_buf,"Formula: ");
  661.     buf=print_buf+9;
  662.     while(*expr) {
  663.         byte= *expr++;
  664.  
  665.         if(byte<USR1)
  666.             f= &the_funs[byte];
  667.         else if(byte<SKIP) {
  668.             tmp_int= *expr++;
  669.             f= &usr_funs[byte-USR1][tmp_int];
  670.         } else
  671.             f= &skip_funs[byte-SKIP];
  672.  
  673.         if(f->fn_argn&X_J)
  674.             jumpto= *expr++;
  675.         else if(f->fn_argn&X_JL) {
  676.             jumpto= expr[0]+((unsigned)(expr[1])<<8);
  677.             expr+=2;
  678.         } else
  679.             jumpto=0;
  680.  
  681.         switch(GET_COMP(f->fn_comptype)) {
  682.         case C_IF:
  683.             sprintf(buf," if%d.%u",byte,jumpto);
  684.             break;
  685.         case C_ANDOR:
  686.             sprintf(buf," andor%d.%u",byte,jumpto);
  687.             break;
  688.         case C_ERR:
  689.             tmp_str=(char *)(expr+jumpto);
  690.             byte= *expr++;
  691.             sprintf(buf," err%d.%p(%s)",byte,tmp_str,tmp_str);
  692.             break;
  693.         case C_FLT:
  694.             bcopy((VOIDSTAR)expr,(VOIDSTAR)&tmp_flt,sizeof(double));
  695.             expr+=sizeof(double);
  696.             sprintf(buf," flt.%.15g",tmp_flt);
  697.             break;
  698.         case C_INT:
  699.             bcopy((VOIDSTAR)expr,(VOIDSTAR)&tmp_int,sizeof(long));
  700.             expr+=sizeof(long);
  701.             sprintf(buf," int.%ld",tmp_int);
  702.             break;
  703.         case C_STR:
  704.             tmp_str=(char *)(expr+jumpto);
  705.             sprintf(buf," str.%p.%s",tmp_str,tmp_str);
  706.             break;
  707.         case C_VAR:
  708.             bcopy((VOIDSTAR)expr,(VOIDSTAR)&v,sizeof(struct var *));
  709.             expr+=sizeof(struct var *);
  710.             sprintf(buf," var.%p.%s",v,v->var_name);
  711.             break;
  712.         case C_CELL:
  713.             sprintf(buf," ref%d.%u.%u",byte,GET_ROW(expr-1),GET_COL(expr-1));
  714.             expr+=EXP_ADD;
  715.             break;
  716.         case C_RANGE:
  717.             GET_RNG(expr,&rng);
  718.             sprintf(buf," rng%d.%u-%u,%u-%u",byte,rng.lr,rng.hr,rng.lc,rng.hc);
  719.             expr+=EXP_ADD_RNG;
  720.             break;
  721.         case C_FN0:
  722.         case C_FN0X:
  723.         case C_FN1:
  724.         case C_FN2:
  725.         case C_FN3:
  726.         case C_FN4:
  727.         case C_UNA:
  728.         case C_INF:
  729.             sprintf(buf," fun%d.%s.%p",byte,f->fn_str,f->fn_fun);
  730.             break;
  731.  
  732.         case C_FNN:
  733.             sprintf(buf," funn%d.%s.%p.%d",byte,f->fn_str,f->fn_fun,*expr++);
  734.             break;
  735.         case C_CONST:
  736.             sprintf(buf," const%s",f->fn_str);
  737.             break;
  738.         case C_SKIP:
  739.             sprintf(buf," skip.%d",jumpto);
  740.             break;
  741.         case 0:
  742.             sprintf(buf," ???%d",byte);
  743.             break;
  744.         default:
  745.             error_msg("Unknown decompile type %d",f->fn_comptype);
  746.         }
  747.         buf+=strlen(buf);
  748.     }
  749.     text_line(print_buf);
  750. }
  751.  
  752. #endif
  753.